<template>
  <div class="table-box" v-loading="options.loading" >
    <el-table ref="table" :data="options.data" stripe border size="small"
              :show-summary="Boolean(summaryMethod)"
              :summary-method="summaryMethod"
              v-bind="$attrs"
              v-on="$listeners">
      <template  v-for="(item,idx) in columns" >
        <!-- common -->
        <el-table-column v-if="showCol(item,'true')" :key="idx" v-bind="{...item}" ></el-table-column>
        <!-- component-global -->
        <el-table-column v-if="showCol(item,'column')" :key="idx" v-bind="{...item}" >
          <component slot-scope="scope" :is="item.template" :scope="scope" :column="item" :options="options"/>
        </el-table-column>
        <el-table-column v-if="showCol(item,'col')" :key="idx" v-bind="{...item}" >
          <slot slot-scope="scope" :name="item.template" :row="scope.row" :column="item"/>
        </el-table-column>
        <!-- component-slot -->
        <slot v-if="showCol(item,'slot')" :name="item.template" :column="item" />
        <el-table-column v-else-if="showCol(item,'_')" :key="idx" :showOverflowTooltip="false" :class-name="item.className||'buttons'" v-bind="{...item}" >
          <template slot-scope="scope">
            <template v-for="(button,buttonIdx) in item.options"  >
              <el-button
                :type="button.type||'text'"
                :size="button.size||'mini'"
                :key="buttonIdx"
                v-if="!button.onShow || button.onShow(scope.row)"
                v-bind="button.props"
                v-hasPermi="button.hasPermi || []"
                @click="button.onClick(scope.row)"
              >
                <!--<i :class="`icon ${button.icon}`" />-->
                {{button.text}}
              </el-button>
            </template>
            <el-dropdown class="selection" v-if="Boolean(item.dropOptions)" @command="(idx)=>{handleDropdown(item,idx,scope.row)}">
              <span class="el-dropdown-link">
                更多<i class="el-icon-arrow-down el-icon--right"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item
                  v-for="(one,oneIdx) in item.dropOptions"
                  v-show="!one.onShow || one.onShow(scope.row)"
                  v-hasPermi="one.hasPermi || []"
                  :command="oneIdx">{{one.text}}</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <Pagination
      v-if="options.total>0"
      :total="options.total"
      :page.sync="options.pageNum"
      :page-sizes="options.pageSizes || [10,50,100,500,1000]"
      :limit.sync="options.pageSize"
      :autoScroll="autoScroll"
      @pagination="onPage"
    />
  </div>
</template>

<script>
  const path = require('path')
  const files = require.context('./column', false, /\.vue$/)
  const modules = {}
  files.keys().forEach(key => {
    const name = path.basename(key, '.vue') // 提取出用 ‘/' 隔开的path的最后一部分,path.basename(p, [ext])。 p要处理的path,ext要过滤的字符
    modules['Column'+name] = files(key).default || files(key)
  })
  let TO_TYPE = (a,b)=>Object.prototype.toString.call(a) == b;

  export default {
    name:'Table',
    components:modules,
    dicts:[],
    props:{
      columns:{
        type:Array
      },
      options:{
        type:Object,
        default:()=>({
          loading:false
        })
      },
      summaryMethod:{
        type:Function
      },
      autoScroll:{
        type:Boolean,
        default:false
      },
    },
    watch:{
      'options.total':{
        handler(val){
          let op = this.options;
          // 加载返回分页信息：分页过大则重新加载最后一页信息
          let page = Math.ceil(val/op.pageSize);
          if(op.pageNum > 1 && (op.pageNum > page)){
            this.$emit("getList",{pageNum:page})
          }
        }
      },
      'options.oriData':{
        handler(val){
          this.onPage();
        }
      },
      "options.columns":{
        handler(cols){
          let columns = this.columns;
          cols.forEach((col)=>{
            columns[col.key]['hidden'] = !col.visible;
          })
          //
          if(this.$attrs.height){
            setTimeout(()=>this.$refs.table.doLayout())
          }
        }
      },
    },
    created(){window.table = this;
      this.initDict();
    },
    mounted(){
      this.options.columns && this.getListColumns();
    },
    methods:{
      initDict(){
        let columns = this.columns;
        let taskCol = [];
        let taskList = [];
        columns.forEach((v,i)=>{
          _.defaults(v,{showOverflowTooltip:true});
          if(v.prop != '_' && v.options){
            let task = v.options;
            if(TO_TYPE(v.options,"[object String]")){
              task = this.dict.init([v.options]).then(([data])=>data);
            }
            v.formatter = (row)=>row[v.prop];
            taskCol.push(v);
            taskList.push(task);
          }
        })
        //
        Promise.all(taskList).then((list)=>{
          let result = {};// k:{col,task}
          taskCol.map((n,i)=>{
            n.optionsData = list[i];
            result[n.prop] = n;
          });
          this.$refs.table.columns.map((column)=>{
            const oriCol = result[column.property];
            if(oriCol){
              column.formatter = (row,col)=>{
                let arr = this.dict.getRows(oriCol.optionsData,row[oriCol.prop])
                if(oriCol.onText){
                  return oriCol.onText(row,arr);
                }else{
                  oriCol.listClass = arr.listClass;
                  return arr.label;
                }
              }
            }
          })
        })
      },
      showCol(column,name){
        return this.getType(column) === name;
      },
      // 展示列表列
      getListColumns(){
        let key = this.$store.getters.name + '_' + this.$route.path;
        let obj = JSON.parse(localStorage.cacheColumn||'{}');
        let list = obj[key];
        let cols = [];
        if(this.options.columns.length === 0){
          this.columns.forEach((v,i)=>{
            if(list){
              v.hidden = list.indexOf(i)>-1;
            }
            //
            if(v.prop != "_" && v.label && !v.affix){
              cols.push({key:i,label:v.label,visible:!v.hidden});
            }
          })
          this.options.columns = cols;
        }
      },
      getType:(item)=>{
        let type = '';
        if(item.hidden){
          return type
        }
        //
        if(item.template){
          if(/^Column/.test(item.template)){
            type = 'column'
          }else if(/^Col/.test(item.template)){
            type = 'col'
          }else{
            type = 'slot'
          }
        }else if(item.prop === '_'){
          type = '_';
        }else{
          type = 'true'
        }
        return type;
      },
      handleButtonClick(item,row){
        return true;
      },
      handleDropdown(item,idx,row){
        let btn = item.dropOptions[idx];
        if(btn.onClick){
          btn.onClick(row);
        }
      },
      setColOptions(opt){
        this.columns.map((col)=>{
          let key = col.type || col.prop;
          if(opt[key]){
            Object.assign(col,opt[key])
          }
        })
        this.$forceUpdate();
      },
      refresh(){
        this.$refs.table.columns.splice(0,0);
      },
      // 分页 - 刷新事件
      onPage(page){
        let options = this.options;
        if(options.localPage){
          let oriData = options.oriData || [];
          let pageSize = options.pageSize||10;
          let start = ((options.pageNum||1) - 1) * pageSize;
          let end = start + pageSize;
          options.data = oriData.slice(start,end);
          options.total = oriData.length;
        }else{
          this.$emit("getList",page)
        }
      }
    }
  }
</script>
<style lang="scss">
  .table-box{
    .el-button--text{
      span{margin-left:0;}
    }

    /* 特殊行样式展示：合计 */
    .total-row{
      font-weight: 700;

      td{
        background: #f8ffe4 !important
      }
    }

    .el-button--text.success{
      color:#67c23a;
    }

    .el-button--text.info{
      color:#909399;
    }

    .el-button--text.warning{
      color:#e6a23c;
    }

    .el-button--text.danger{
      color:#f56c6c;
    }

    .column_money{
      font-weight: 700;
    }
  }
</style>
